home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / bsd_src / glob.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-04  |  9.2 KB  |  448 lines

  1. #define NCARGS 2000
  2. /*
  3.  * Copyright (c) 1980 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that the above copyright notice and this paragraph are
  8.  * duplicated in all such forms and that any documentation,
  9.  * advertising materials, and other materials related to such
  10.  * distribution and use acknowledge that the software was developed
  11.  * by the University of California, Berkeley.  The name of the
  12.  * University may not be used to endorse or promote products derived
  13.  * from this software without specific prior written permission.
  14.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  15.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  16.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  17.  */
  18.  
  19. /* 24-DEC-92 Modified for use with VMS-fsp V2.6.3  <S.A.Pechler@bdk.tue.nl>
  20.  * 27-JAN-93 Stripped leading spaces in arguments  <S.A.Pechler@bdk.tue.nl>
  21.  * 17-MAY-93 Removed all VMS modifications         <S.A.Pechler@bdk.tue.nl>
  22.  */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#)glob.c    5.4 (Berkeley) 6/29/88";
  26. #endif /* not lint */
  27.  
  28. /*
  29.  * C-shell glob for random programs.
  30.  */
  31.  
  32. #include "tweak.h"
  33. #include "client_def.h"
  34. #include "c_extern.h"
  35.  
  36. #define    QUOTE 0200
  37. #define    TRIM 0177
  38. #define    eq(a,b)        (strcmp(a, b)==0)
  39. #define    GAVSIZ        (NCARGS/6)
  40. #define    isdir(d)    ((d.st_mode & S_IFMT) == S_IFDIR)
  41.  
  42. static    char **gargv;        /* Pointer to the (stack) arglist */
  43. static    int gargc;        /* Number args in gargv */
  44. static    int gnleft;
  45. static    int gflag;
  46. char    *globerr;
  47. extern    int errno;
  48.  
  49. static    int globcnt;
  50.  
  51. char    *globchars = "`{[*?";
  52.  
  53. static    char *gpath, *gpathp, *lastgpathp;
  54. static    int globbed;
  55. static    char *entp;
  56. static    char **sortbas;
  57.  
  58. static int any PROTO2(register int, c, register char *, s)
  59. {
  60.   while (*s)
  61.     if (*s++ == c) return(1);
  62.   return(0);
  63. }
  64.  
  65. static int tglob PROTO1(char, c)
  66. {
  67.   if (any(c, globchars))
  68.     gflag |= c == '{' ? 2 : 1;
  69.   return (c);
  70. }
  71.  
  72. static int addpath PROTO1(char, c)
  73. {
  74.   if (gpathp >= lastgpathp) globerr = "Pathname too long";
  75.   else {
  76.     *gpathp++ = c;
  77.     *gpathp = 0;
  78.   }
  79. }
  80.  
  81. static int ginit PROTO1(char **, agargv)
  82. {
  83.   agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  84.   gnleft = NCARGS - 4;
  85. }
  86.  
  87. static int sort PROTO0((void))
  88. {
  89.   register char **p1, **p2, *c;
  90.   char **Gvp = &gargv[gargc];
  91.  
  92.   p1 = sortbas;
  93.   while (p1 < Gvp-1) {
  94.     p2 = p1;
  95.     while (++p2 < Gvp)
  96.       if (strcmp(*p1, *p2) > 0) {
  97.         c = *p1;
  98.     *p1 = *p2;
  99.     *p2 = c;
  100.       }
  101.     p1++;
  102.   }
  103.   sortbas = Gvp;
  104. }
  105.  
  106. static char *strspl PROTO2(register char *, cp, register char *, dp)
  107. {
  108.   register char *ep = (char *)malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
  109.  
  110.   if (ep == (char *)0) {
  111.     perror("Out of memory 1");
  112.     exit(1);
  113.   }
  114.   (void) strcpy(ep, cp);
  115.   (void) strcat(ep, dp);
  116.   return (ep);
  117. }
  118.  
  119. static int Gcat PROTO2(char *, s1, char *, s2)
  120. {
  121.   register int len = strlen(s1) + strlen(s2) + 1;
  122.  
  123.   if (len >= gnleft || gargc >= GAVSIZ - 1) globerr = "Arguments too long";
  124.   else {
  125.     gargc++;
  126.     gnleft -= len;
  127.     gargv[gargc] = 0;
  128.     gargv[gargc - 1] = strspl(s1, s2);
  129.   }
  130. }
  131.  
  132. static int execbrc PROTO0((char *, char *));
  133.  
  134. static int expand PROTO1(char *, as)
  135. {
  136.   register char *cs;
  137.   register char *sgpathp, *oldcs;
  138.   struct stat stb;
  139.  
  140.   sgpathp = gpathp;
  141.   cs = as;
  142.   while (!any(*cs, globchars)) {
  143.     if (*cs == 0) {
  144.       if (!globbed) Gcat(gpath, "");
  145.       else if (util_stat(gpath, &stb) >= 0) {
  146.         Gcat(gpath, "");
  147.         globcnt++;
  148.       }
  149.       break;
  150.     }
  151.     addpath(*cs++);
  152.   }
  153.   if(*cs) {
  154.     oldcs = cs;
  155.     while (cs > as && *cs != '/') {
  156.       cs--; gpathp--;
  157.     }
  158.     if (*cs == '/') {
  159.       cs++; gpathp++;
  160.     }
  161.     *gpathp = 0;
  162.     if (*oldcs == '{') {
  163.       (void) execbrc(cs, ((char *)0));
  164.       return;
  165.     }
  166.     matchdir(cs);
  167.   }
  168.   gpathp = sgpathp;
  169.   *gpathp = 0;
  170. }
  171.  
  172. static int amatch PROTO2(char *, s, char *, p)
  173. {
  174.   register int scc;
  175.   int ok, lc;
  176.   char *sgpathp;
  177.   struct stat stb;
  178.   int c, cc;
  179.  
  180.   globbed = 1;
  181.   for (;;) {
  182.     scc = *s++ & TRIM;
  183.     switch (c = *p++) {
  184.       case '{':
  185.         return (execbrc(p - 1, s - 1));
  186.       case '[':
  187.         ok = 0;
  188.         lc = 077777;
  189.         while (cc = *p++) {
  190.           if (cc == ']') {
  191.             if (ok) break;
  192.             return (0);
  193.           }
  194.           if (cc == '-') {
  195.             if (lc <= scc && scc <= *p++) ok++;
  196.           } else if (scc == (lc = cc)) ok++;
  197.         }
  198.         if (cc == 0) {
  199.           if (ok) p--;
  200.           else return 0;
  201.         }
  202.         continue;
  203.       case '*':
  204.         if (!*p) return (1);
  205.         if (*p == '/') {
  206.           p++;
  207.           goto slash;
  208.         }
  209.         s--;
  210.         do {
  211.           if (amatch(s, p)) return (1);
  212.         } while (*s++);
  213.         return (0);
  214.       case 0:
  215.         return (scc == 0);
  216.       default:
  217.         if (c != scc) return (0);
  218.         continue;
  219.       case '?':
  220.         if (scc == 0) return (0);
  221.         continue;
  222.       case '/':
  223.         if (scc) return (0);
  224. slash:
  225.         s = entp;
  226.         sgpathp = gpathp;
  227.         while (*s) addpath(*s++);
  228.         addpath('/');
  229.         if (util_stat(gpath, &stb) == 0 && isdir(stb))
  230.           if (*p == 0) {
  231.             Gcat(gpath, "");
  232.             globcnt++;
  233.           } else expand(p);
  234.         gpathp = sgpathp;
  235.         *gpathp = 0;
  236.         return (0);
  237.     }
  238.   }
  239. }
  240.  
  241. static int match PROTO2(char *, s, char *, p)
  242. {
  243.   register int c;
  244.   register char *sentp;
  245.   char sglobbed = globbed;
  246.  
  247.   if (*s == '.' && *p != '.') return (0);
  248.   sentp = entp;
  249.   entp = s;
  250.   c = amatch(s, p);
  251.   entp = sentp;
  252.   globbed = sglobbed;
  253.   return (c);
  254. }
  255.  
  256. int matchdir PROTO1(char *, pattern)
  257. {
  258.   struct stat stb;
  259.   register struct rdirent *dp;
  260.   RDIR *dirp;
  261.  
  262.   dirp = util_opendir(gpath);
  263.   if (dirp == NULL) {
  264.     if (globbed) return;
  265.     globerr = "Bad directory components";
  266.     return;
  267.   }
  268.   if (util_stat(gpath, &stb) < 0) {
  269.     util_closedir(dirp);
  270.     globerr = "Bad directory components";
  271.   }
  272.   if (!isdir(stb)) {
  273.     errno = ENOTDIR;
  274.     util_closedir(dirp);
  275.     globerr = "Bad directory components";
  276.   }
  277.   while ((dp = util_readdir(dirp)) != NULL) {
  278.     if (dp->d_fileno == 0) continue;
  279.     if (match(dp->d_name, pattern)) {
  280.       Gcat(gpath, dp->d_name);
  281.       globcnt++;
  282.     }
  283.   }
  284.   util_closedir(dirp);
  285. }
  286.  
  287. static int execbrc PROTO2(char *, p, char *, s)
  288. {
  289.   char restbuf[BUFSIZ + 2];
  290.   register char *pe, *pm, *pl;
  291.   int brclev = 0;
  292.   char *lm, savec, *sgpathp;
  293.  
  294.   for (lm = restbuf; *p != '{'; *lm++ = *p++);
  295.   for (pe = ++p; *pe; pe++)
  296.     switch (*pe) {
  297.       case '{':
  298.         brclev++;
  299.         continue;
  300.       case '}':
  301.         if (brclev == 0) goto pend;
  302.         brclev--;
  303.         continue;
  304.       case '[':
  305.         for (pe++; *pe && *pe != ']'; pe++);
  306.     }
  307. pend:
  308.   brclev = 0;
  309.   for (pl = pm = p; pm <= pe; pm++)
  310.     switch (*pm & (QUOTE|TRIM)) {
  311.       case '{':
  312.         brclev++;
  313.         continue;
  314.       case '}':
  315.         if (brclev) {
  316.           brclev--;
  317.           continue;
  318.       }
  319.       goto doit;
  320.       case ','|QUOTE:
  321.       case ',':
  322.         if (brclev) continue;
  323. doit:
  324.         savec = *pm;
  325.         *pm = 0;
  326.     (void) strcpy(lm, pl);
  327.         (void) strcat(restbuf, pe + 1);
  328.         *pm = savec;
  329.         if (s == 0) {
  330.           sgpathp = gpathp;
  331.           expand(restbuf);
  332.           gpathp = sgpathp;
  333.           *gpathp = 0;
  334.         } else if (amatch(s, restbuf)) return (1);
  335.         sort();
  336.         pl = pm + 1;
  337.         if (brclev) return (0);
  338.         continue;
  339.       case '[':
  340.         for (pm++; *pm && *pm != ']'; pm++);
  341.         if (!*pm) pm--;
  342.     continue;
  343.     }
  344.     if (brclev) goto doit;
  345.     return (0);
  346. }
  347.  
  348. int acollect PROTO1(register char *, as)
  349. {
  350.   register int ogargc = gargc;
  351.  
  352.   gpathp = gpath; *gpathp = 0; globbed = 0;
  353.   expand(as);
  354.   if (gargc != ogargc) sort();
  355. }
  356.  
  357. static int collect PROTO1(register char *, as)
  358. {
  359.   if (eq(as, "{") || eq(as, "{}")) {
  360.     Gcat(as, "");
  361.     sort();
  362.   } else acollect(as);
  363. }
  364.  
  365. static int blkfree PROTO1(char **, av0)
  366. {
  367.   register char **av = av0;
  368.  
  369.   while (*av) free(*av++);
  370. }
  371.  
  372. static int blklen PROTO1(register char **, av)
  373. {
  374.   register int i = 0;
  375.  
  376.   while (*av++) i++;
  377.   return (i);
  378. }
  379.  
  380. static char **blkcpy PROTO2(char **, oav, register char **, bv)
  381. {
  382.   register char **av = oav;
  383.  
  384.   while (*av++ = *bv++) continue;
  385.   return (oav);
  386. }
  387.  
  388. static char **copyblk PROTO1(register char **, v)
  389. {
  390.   register char **nv;
  391.  
  392.   nv = (char **)malloc((unsigned)((blklen(v) + 1) * sizeof(char **)));
  393.   if (nv == (char **)0) {
  394.     perror("Out of memory 2");
  395.     exit(2);
  396.   }
  397.   return (blkcpy(nv, v));
  398. }
  399.  
  400. #ifdef HAVE_ANSI_PROTO
  401. typedef int (*charfunc) (char) ;
  402. static int rscan (register char **t, charfunc f)
  403. #else
  404. static int rscan(t, f)
  405.     register char **t;
  406.     int (*f)();
  407. #endif
  408. {
  409.   register char *p, c;
  410.  
  411.   while (p = *t++) {
  412. #ifdef HAVE_ANSI_PROTO
  413.     if (f == (charfunc) tglob)
  414. #else
  415.     if (f == tglob) 
  416. #endif
  417.       if (*p == '~') gflag |= 2;
  418.       else if (eq(p, "{") || eq(p, "{}")) continue;
  419.     while (c = *p++) (*f)(c);
  420.   }
  421. }
  422.  
  423. char **glob PROTO1(register char *, v)
  424. {
  425.   char agpath[BUFSIZ];
  426.   char *agargv[GAVSIZ];
  427.   char *vv[2];
  428.   vv[0] = v;
  429.   vv[1] = 0;
  430.   gflag = 0;
  431. #ifdef HAVE_ANSI_PROTO
  432.   rscan(vv, (charfunc) tglob);
  433. #else
  434.   rscan(vv, tglob);
  435. #endif
  436.   if (gflag == 0) return (copyblk(vv));
  437.  
  438.   globerr = 0;
  439.   gpath = agpath; gpathp = gpath; *gpathp = 0;
  440.   lastgpathp = &gpath[sizeof agpath - 2];
  441.   ginit(agargv); globcnt = 0;
  442.   collect(v);
  443.   if (globcnt == 0 && (gflag&1)) {
  444.     blkfree(gargv), gargv = 0;
  445.     return (0);
  446.   } else return (gargv = copyblk(gargv));
  447. }
  448.